package ws.very.util.aws.s3

import com.amazonaws.services.s3.model.PutObjectRequest
import com.amazonaws.services.s3.AmazonS3Client
import awscala.s3._
import com.amazonaws.services.s3.model.StorageClass
import awscala.CredentialsLoader
import awscala.Region
import awscala.Credentials
import com.amazonaws.services.s3.model.ObjectMetadata
import scala.util.Try
import ws.very.util.lang.IOs

object S3 {

  class S3Client(credentials: Credentials = CredentialsLoader.load())
    extends AmazonS3Client(credentials)
    with S3 {
    override def putObject(putObjectRequest: PutObjectRequest) = {
      putObjectRequest.withStorageClass(StorageClass.ReducedRedundancy)
      super.putObject(putObjectRequest)
    }
    override def createBucket(name: String): Bucket = super.createBucket(name)
  }
  def apply(credentials: Credentials = CredentialsLoader.load()): S3 = new S3Client(credentials)

  def apply(accessKeyId: String, secretAccessKey: String): S3 = apply(Credentials(accessKeyId, secretAccessKey))

  def at(region: Region): S3 = apply().at(region)
}

trait AwsS3BaseDao {
  def accessKeyId: S
  def secretAccessKey: S
  def region: Region

  def bucket: S

  implicit val s3 = S3(accessKeyId, secretAccessKey)
  implicit val t = s3.at(region).bucket(bucket).get

  def metaData(l: L) = {
    val m = new ObjectMetadata()
    m.setContentType("application/octet-stream")
    m.setContentLength(l)
    m
  }
  def saveFileFromBytes(key: S, bytes: Array[Byte]) =
    t.putObjectAsPublicRead(key, bytes, metaData(bytes.length))

  def tryFile2Bytes(key: S) =
    Try {
      t.get(key).map { s3Obj =>
        IOs.toBytesAndClose(s3Obj.content)
      }.get
    }
}
